package com.luck.emp.storage.logic;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.jdbc.core.RowMapper;

import com.luck.emp.common.SpWhOrderD;
import com.luck.emp.common.SpWhOrderM;
import com.luck.emp.entity.EmpTCgD;
import com.luck.emp.entity.EmpTCgDList;
import com.luck.emp.entity.EmpTCgM;
import com.luck.emp.entity.EmpTWhExD;
import com.luck.emp.entity.EmpTWhExM;
import com.luck.emp.storage.qry.StorageQry;
import com.luck.emp.storage.vo.StorageCheck;
import com.luck.emp.storage.vo.StorageCheckDetail;
import com.luck.pf.common.entity.UserBean;
import com.luck.pf.framework.dao.BaseJdbcDao;
import com.luck.pf.framework.logic.BaseLogic;
import com.luck.pf.util.DateUtil;

/**
 * 说明 Copyright: Copyright (c) 2011 深圳**科技
 * 
 * @author
 * 
 */
public class StorageLogic extends BaseLogic implements IStorageLogic {
	private BaseJdbcDao jdbcDao;

	public BaseJdbcDao getJdbcDao() {
		return jdbcDao;
	}

	public void setJdbcDao(BaseJdbcDao jdbcDao) {
		this.jdbcDao = jdbcDao;
	}

	public <T> T findStorageCheckPage(StorageQry qry, Class<T> cls) {
		StringBuffer sql = new StringBuffer();
		Map params = new HashMap();
		sql.append("select v.*   from (                                                            ");
		String billType = qry.getBillType();
		// 查询采购单
		if (StringUtils.isBlank(billType) || billType.equals("11")) {
			sql.append("        select t.V_CG_CODE as code,                                           ");
			sql.append("               d.dept_name outDeptName,                                     ");
			sql.append("               d.dept_name inDeptName");
			sql.append("               ,to_char(t.D_MODI_DATE, 'yyyy-mm-dd hh24:mi:ss') as dt,       ");
			sql.append("               '采购单' billName,                                                     ");
			sql.append("               '11' billType                                                          ");
			sql.append("        from EMP_T_CG_M t, SYS_DEPARTMENT d        ");
			sql.append("              where t.N_DEPT_ID = d.id                               ");
			sql.append("              and t.N_DEPT_ID = :deptId                             ");
			sql.append("              and (t.V_STATUS = '1' or t.V_STATUS = '2')       ");

			if (qry.getStartDate() != null) {
				sql.append(" and t.D_CREATE_DATE >= :beginDated");
				params.put("beginDated", qry.getStartDate());
			}
			if (qry.getEndDate() != null) {
				sql.append(" and t.D_CREATE_DATE < :endDated");
				params.put("endDated", DateUtil.getEndDateDay(qry.getEndDate()));
			}

			if (StringUtils.isNotBlank(qry.getBillNo())) {
				sql.append(" and t.V_CG_CODE like :coded");
				params.put("coded", "%" + qry.getBillNo() + "%");
			}
		}
		if(StringUtils.isBlank(qry.getBillType()))
			sql.append("  union all    ");
		if (StringUtils.isBlank(billType) || billType.equals("13")) {//处理调拨单
			sql.append("SELECT T.V_EX_NO AS CODE, ");
			sql.append("       D1.DEPT_NAME OUTDEPTNAME, ");
			sql.append("       D2.DEPT_NAME INDEPTNAME, ");
			sql.append("       TO_CHAR(T.D_AUDIT_DATE, 'yyyy-mm-dd hh24:mi:ss') AS DT, ");
			sql.append("       '调拨单' BILLNAME, ");
			sql.append("       '13' BILLTYPE ");
			sql.append("  FROM EMP_T_WH_EX_M T, SYS_DEPARTMENT D1, SYS_DEPARTMENT D2 ");
			sql.append(" WHERE T.N_FROM_DEPT_ID = D1.ID ");
			sql.append("   AND T.N_TO_DEPT_ID = D2.ID ");
			sql.append("   AND T.V_STATUS IN ('18', '22', '26') ");
			sql.append("   AND T.N_TO_DEPT_ID =:deptId ");
			
					
			if (qry.getStartDate() != null) {
				sql.append(" and t.D_AUDIT_DATE >= :beginDated");
				params.put("beginDated", qry.getStartDate());
			}
			if (qry.getEndDate() != null) {
				sql.append(" and t.D_AUDIT_DATE < :endDated");
				params.put("endDated", DateUtil.getEndDateDay(qry.getEndDate()));
			}

			if (StringUtils.isNotBlank(qry.getBillNo())) {
				sql.append(" and t.V_EX_NO like :coded");
				params.put("coded", "%" + qry.getBillNo() + "%");
			}
		}
		sql.append(" ) v order by v.dt desc                                                              ");

		//System.out.println(sql.toString());
		params.put("deptId", qry.getUserInfo().getDeptId());
		if (cls.getName().equals("java.util.List")) {
			return (T) this.jdbcDao.queryForList(sql.toString(), params,
					exCheckRw);
		} else {
			return (T) this.jdbcDao.queryForPage(sql.toString(), params,
					qry.getPageNo(), qry.getPageSize(), exCheckRw);
		}
	}

	private static final ExCheckRw exCheckRw = new ExCheckRw();

	private static final class ExCheckRw implements RowMapper {
		public Object mapRow(ResultSet rs, int rownum) throws SQLException {
			StorageCheck vo = new StorageCheck();
			vo.setIndex(rownum + 1);
			vo.setBillNo(rs.getString(1));
			vo.setOutDeptName(rs.getString(2));
			vo.setInDeptName(rs.getString(3));
			vo.setCheckDate(rs.getString(4));
			vo.setBillName(rs.getString(5));
			vo.setBillType(rs.getString(6));
			return vo;
		}
	}

	public List<StorageCheckDetail> findStorageCheckDetailPage(StorageQry qry) {
		StringBuffer sql = new StringBuffer();
		Map params = new HashMap();
		if (StringUtils.isBlank(qry.getBillType())
				|| qry.getBillType().equals("11")) {// 采购单
			sql.append(" select t.V_PRODUCT_CODE, ");
			sql.append(" p.V_PROD_BARCODE, ");
			sql.append(" p.V_NAME, ");
			sql.append(" t.n_qty, ");
			sql.append(" t.n_qty - t.n_confirm_in stayqty, ");
			sql.append(" t.n_qty - t.n_confirm_in inqty, ");
			sql.append(" trim(to_char(t.N_PUR_PRICE, '99999999990.99')) N_PRICE, ");// 单价
			sql.append(" t.N_PRICE_REAL N_PRICE_REAL, ");// 实际价格
			sql.append(" p.V_NOTE, ");
			sql.append(" t.N_CGD_ID n_ex_d_id ");
			sql.append(" from EMP_T_CG_D t, EMP_T_PROD_BASE p, EMP_T_CG_D M ");
			sql.append(" where t.V_CG_CODE = :billNo   ");
			sql.append(" and T.V_CG_CODE = m.V_CG_CODE ");
			sql.append(" and T.V_PRODUCT_CODE = p.V_PRODUCT_CODE ");
			sql.append(" and t.N_QTY - t.N_CONFIRM_IN>0 order by T.V_PRODUCT_CODE ");
		} else if (qry.getBillType().equals("13")){
			sql.append("SELECT T.V_PRODUCT_CODE, ");
			sql.append("       P.V_PROD_BARCODE, ");
			sql.append("       P.V_NAME, ");
			sql.append("       T.N_CONFIRM_OUT N_QTY , ");
			sql.append("       T.N_CONFIRM_OUT - T.N_CONFIRM_IN STAYQTY, ");
			sql.append("       T.N_CONFIRM_OUT - T.N_CONFIRM_IN INQTY, ");
			sql.append("       TRIM(TO_CHAR(T.N_PRICE, '99999999990.99')) N_PRICE, ");
			sql.append("       0 N_PRICE_REAL, ");
			//sql.append("       T.N_PUR_PRICE N_PRICE_REAL, ");
			sql.append("       M.V_NOTE, ");
			sql.append("       T.N_EX_D_ID N_EX_D_ID ");
			sql.append("  FROM EMP_T_WH_EX_D T, EMP_T_PROD_BASE P, EMP_T_WH_EX_M M ");
			sql.append(" WHERE T.V_EX_NO =:billNo ");
			sql.append("   AND T.V_EX_NO = M.V_EX_NO ");
			sql.append("   AND T.V_PRODUCT_CODE = P.V_PRODUCT_CODE ");
			sql.append("   AND T.N_CONFIRM_OUT - T.N_CONFIRM_IN > 0 ");
			sql.append(" ORDER BY T.V_PRODUCT_CODE ");

		}

		params.put("billNo", qry.getBillNo());
		//System.out.println(sql.toString());
		return this.jdbcDao.queryForList(sql.toString(), params,
				exCheckDetailRw);
	}

	private static final ExCheckDetailRw exCheckDetailRw = new ExCheckDetailRw();

	private static final class ExCheckDetailRw implements RowMapper {
		public Object mapRow(ResultSet rs, int rownum) throws SQLException {
			StorageCheckDetail vo = new StorageCheckDetail();
			vo.setIndex(rownum + 1);
			vo.setProductCode(rs.getString("V_PRODUCT_CODE"));
			vo.setProductName(rs.getString("V_NAME"));
			vo.setProdBarcode(rs.getString("V_PROD_BARCODE"));
			// vo.setWhProdStock(rs.getLong("WH_PROD_STOCK"));
			vo.setQty(rs.getLong("N_QTY"));
			vo.setStayQty(rs.getLong("stayqty"));
			vo.setInQty(rs.getLong("inqty"));
			vo.setPrice(rs.getString("N_PRICE"));
			vo.setRealPrice(rs.getString("N_PRICE_REAL"));
			vo.setNote(rs.getString("V_NOTE"));
			vo.setExDId(rs.getLong("N_EX_D_ID"));
			return vo;
		}
	}

	// 采购入库确认
	public String saveStorageCheckCg(UserBean userInfo, EmpTCgM cgm,
			StorageCheck check, String whCode, Long[] exDIds,
			String[] productCodes, String[] stayInQtys, String[] inQtys,
			String[] realPrices, String flowStatus, String ioType,
			String channelType, Long custId, Long salemanId) throws Exception {
		StringBuffer bf = new StringBuffer();
		// 采购单
		String billType = check.getBillType();
		SpWhOrderM sp = new SpWhOrderM(this.jdbcDao.getJdbcTemplate());
		String orderCode = sp.execute(billType, 20L, cgm.getCgCode(), whCode, cgm.getVendorCode(), 
				cgm.getContact(), cgm.getTel(), cgm.getContactAddr(), cgm.getNote(), userInfo.getUserId(), ioType, channelType, custId, salemanId);
		boolean flag = false;//为真是表示未完成全部入库，单据不能完结
		SpWhOrderD spd = new SpWhOrderD(this.jdbcDao.getJdbcTemplate());
		for (int i = 0, len = productCodes.length; i < len; i++) {
			if (StringUtils.isEmpty(inQtys[i])) {
				flag = true;
				continue;
			}
			// 入库数量
			long inQty = Long.parseLong(inQtys[i]);
			// 待入库数量
			long stayQty = Long.parseLong(stayInQtys[i]);
			if (inQty > Long.valueOf(0)) {
				// 设置入库数量，实际价格
				EmpTCgD cgd = get(EmpTCgD.class, exDIds[i]);
				//保证入库记录插入EmpTCgDList（采购入库明细表）,真实反映发生的采购金额。对于供应商结算金额
				EmpTCgDList dlist = new EmpTCgDList();
				dlist.setCgdId(exDIds[i]);
				dlist.setConfirmIn(inQty);
				dlist.setHxStatus("1");//未核销
				dlist.setInDate(DateUtil.getDate());
				dlist.setPayAmt(0.00);
				dlist.setPriceReal(Double.parseDouble(realPrices[i]));
				dlist.setProductCode(cgd.getProductCode());
				super.save(dlist);
				
				cgd.setConfirmIn(cgd.getConfirmIn()+inQty);//确认数量
				cgd.setPriceReal(Double.valueOf(realPrices[i]));// 实际采购价格

				// 插入订单明细表
				spd.execute(orderCode, productCodes[i], inQty, 0, 0, userInfo.getUserId(), null);
				// 保存明细
				super.save(cgd);
				if (inQty != stayQty) {
					flag = true;
				}
			} else {
				flag = true;
			}
		}
		//处理采购单状态,flowStatus:1为保存，2：完结
		if(flowStatus.equals("2")){
			cgm.setStatus("6");//完结
		}else{
			if (flag) {
				// 部分入库
				cgm.setStatus("2");//部分入库
			} else {
				// 全部入库
				cgm.setStatus("6");//完结
			}
		}
		cgm.setModiDate(DateUtil.getDate());
		cgm.setModiUser(userInfo.getUser());
		super.save(cgm);

		// 插入处理跟踪流水表

		// 调仓储接口,更新调拨单状态

		return bf.toString();
	}
	//调拨确认入库
	public String saveStorageCheckEx(UserBean userInfo, EmpTWhExM exm,
			StorageCheck check, String whCode, Long[] exDIds,
			String[] productCodes,  String[] stayInQtys, String[] inQtys, String flowStatus, String ioType,
			String channelType, Long custId, Long salemanId) throws Exception{
		StringBuffer bf = new StringBuffer();

		if(flowStatus.equals("2")){
			throw new Exception("调拨单不能完结");
		}
		// 调拨单
		String billType = check.getBillType();
		SpWhOrderM sp = new SpWhOrderM(this.jdbcDao.getJdbcTemplate());
		String orderCode = sp.execute(billType, 20L, exm.getExNo(), whCode, null, 
				exm.getContact(), exm.getTel(), null, exm.getNote(), userInfo.getUserId(), ioType, channelType, custId, salemanId);
		boolean flag = false;//为真是表示未完成全部入库，单据不能完结
		SpWhOrderD spd = new SpWhOrderD(this.jdbcDao.getJdbcTemplate());
		for (int i = 0, len = productCodes.length; i < len; i++) {
			if (StringUtils.isEmpty(inQtys[i])) {
				flag = true;
				continue;
			}
			// 入库数量
			long inQty = Long.parseLong(inQtys[i]);
			// 待入库数量
			long stayQty = Long.parseLong(stayInQtys[i]);
			if (inQty > Long.valueOf(0)) {
				// 设置入库数量，实际价格
				EmpTWhExD cgd = get(EmpTWhExD.class, exDIds[i]);
				cgd.setConfirmIn(cgd.getConfirmIn()+inQty);//确认数量
				// 插入订单明细表
				spd.execute(orderCode, productCodes[i], inQty, 0, 0, userInfo.getUserId(), null);
				// 保存明细
				super.save(cgd);
				if (inQty != stayQty) {
					flag = true;
				}
			} else {
				flag = true;
			}
		}
		//处理采购单状态,flowStatus:1为保存，2：完结
		if (flag) {
			// 部分入库
			exm.setStatus("26");//部分入库
		} else {
			// 全部入库
			exm.setStatus("30");//完成入库
		}
		exm.setModiDate(DateUtil.getDate());
		exm.setModiUser(userInfo.getUser());
		exm.setToWhCode(whCode);
		
		super.save(exm);

		// 插入处理跟踪流水表

		// 调仓储接口,更新调拨单状态

		return bf.toString();
	}

}